package com.zmn.brs.business.impl.objective;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.ltsopensource.core.domain.Job;
import com.zmn.brs.business.interfaces.dingtalk.DingTalkBService;
import com.zmn.brs.business.interfaces.objective.ObjectiveTargetBService;
import com.zmn.brs.business.interfaces.objective.ObjectiveWarnBService;
import com.zmn.brs.common.constant.BrsConst;
import com.zmn.brs.common.constant.TaskConst;
import com.zmn.brs.common.enums.WronLevelEnum;
import com.zmn.brs.drools.bean.ObjectiveMonitor;
import com.zmn.brs.drools.bean.KieBaseTemplate;
import com.zmn.brs.drools.bean.ObjectiveMonitorData;
import com.zmn.brs.dubbo.constant.DubboConsts;
import com.zmn.brs.model.bo.event.RuleExecuteResultBO;
import com.zmn.brs.model.entity.objective.record.ObjectiveRecord;
import com.zmn.brs.model.entity.objective.record.ObjectiveRecordQuery;
import com.zmn.brs.model.entity.record.EventRecord;
import com.zmn.brs.model.entity.scene.Scene;
import com.zmn.brs.model.entity.task.version.TaskVersion;
import com.zmn.brs.model.query.rule.ObjectiveRuleCustom;
import com.zmn.brs.model.query.rule.ObjectiveRuleCustomQuery;
import com.zmn.brs.model.result.OperateRecordResult;
import com.zmn.brs.model.vo.rule.objective.ObjectiveRuleVO;
import com.zmn.brs.services.interfaces.objective.record.ObjectiveRecordService;
import com.zmn.brs.services.interfaces.objective.rule.ObjectiveRuleService;
import com.zmn.brs.services.interfaces.record.EventRecordService;
import com.zmn.brs.services.interfaces.rule.AlarmRuleService;
import com.zmn.brs.services.interfaces.scene.SceneService;
import com.zmn.brs.services.interfaces.task.version.TaskVersionService;
import com.zmn.brs.utils.BrsUtil;
import com.zmn.common.dto2.ReportDTO;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.cube.common.dto.objective.CustomObjectiveDIO;
import com.zmn.cube.common.dto.objective.CustomObjectiveScopeDIO;
import com.zmn.cube.dubbo.dto.SnapshotReportDIO;
import com.zmn.cube.dubbo.interfaces.board.BoardRemoteService;
import com.zmn.mcc.common.dto.dept.DeptDRO;
import com.zmn.mcc.dubbo.interfaces.dept.DeptListRemoteService;
import com.zmn.okr.common.constant.ObjectiveMasterTypeConst;
import com.zmn.okr.common.model.dio.objective.ObjectiveDIO;
import com.zmn.okr.common.model.dio.objective.scope.ObjectiveScopeDIO;
import com.zmn.okr.dubbo.interfaces.objective.ObjectiveRemoteService;
import com.zmn.plat.common.dictionary.StatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.joda.time.DateTime;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.AgendaFilter;
import org.kie.api.runtime.rule.FactHandle;
import org.kie.api.runtime.rule.Match;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 描述：目标指标监控
 * @author chongw
 * @since 2021-06-07 17:50
 */
@Slf4j
@Service
public class ObjectiveTargetBServiceImpl implements ObjectiveTargetBService {

    public static final String TAG = "目标指标监控业务服务实现";

    @Resource
    private ObjectiveRuleService objectiveRuleService;

    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private BoardRemoteService boardRemoteService;

    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private ObjectiveRemoteService objectiveRemoteService;

    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private DeptListRemoteService deptListRemoteService;

    @Resource
    private ObjectiveRecordService objectiveRecordService;

    @Resource
    private KieBaseTemplate kieBaseTemplate;

    @Resource
    private EventRecordService eventRecordService;

    @Resource
    private AlarmRuleService alarmRuleService;

    @Resource
    private SceneService sceneService;

    @Resource
    private RedisTemplate<String,String> redisTemplate;

    @Resource
    private TaskVersionService taskVersionService;

    @Resource
    private ObjectiveWarnBService objectiveWarnBService;

    @Resource
    private DingTalkBService dingTalkBService;

    /**
     * 描述：目标指标监控定时任务
     * @param job 任务job
     * @return
     * @author chongw
     * @since 2021-06-07 17:50
     */
    @Override
    public Boolean computeObjectiveTask(Job job){
        Date now = DateUtil.getNow();
        //获取当年1月1日
        Date yearFirstDate = DateUtil.getYearStart(new DateTime(now).getYear());
        //获取场景ID
        Integer sceneId = Integer.parseInt(job.getParam(TaskConst.SCENE_ID));
        //获取任务ID
        String taskId = job.getTaskId();
        //生成任务版本号 UUID
        String taskVersionId = TaskConst.getBrsSceneTaskVersion(taskId);
        try {
            //获取作业类型
            Integer jobType = Integer.parseInt(job.getParam(TaskConst.JOB_TYPE));
            //获取场景
            Scene scene = sceneService.findById(sceneId);
            if(scene == null){
                log.error("[{}], 场景ID：{} ,未找到数据！", TAG, sceneId);
                return false;
            }
            if(StatusEnum.DISABLE.getCode().equals(scene.getStatus())){
                log.error("[{}], 场景ID：{} , 事件状态已被停用！", TAG, sceneId);
                return false;
            }
            log.info("[{}], 场景ID：{} ,定时任务开始执行，执行时间：{}", TAG, sceneId, DateUtil.getNowFormatted());
            ObjectiveRuleCustomQuery query = ObjectiveRuleCustomQuery.builder()
                    .sceneId(sceneId)
                    .objMasterType(ObjectiveMasterTypeConst.MASTERTYPE_PERSON)
                    .build();
            //查询所有绩效规则
            List<ObjectiveRuleCustom> objectiveRuleCustomList = Optional.ofNullable(objectiveRuleService.listObjectiveRuleByQuery(query)).orElse(new ArrayList<>());
            //判断规则对象是否为空
            if (objectiveRuleCustomList.isEmpty()) {
                log.error("[{}], 场景ID：{} , 未找到相关配置！", TAG, sceneId);
                return false;
            }
            objectiveRuleCustomList.forEach(o -> {
                Integer ruleId = o.getRuleId();
                Integer thresholdId = o.getThresholdId();
                ObjectiveRuleVO vo = JSONObject.parseObject(o.getThresholdValue(), ObjectiveRuleVO.class);
                try {
                    //判断目标ID是否为空
                    if(NumberUtil.isNullOrZero(vo.getSubgoalId())){
                        log.error("[{}], 场景ID：{} , 目标规则阈值ID：{} , 当前目标ID为空！！！", TAG, sceneId, thresholdId);
                        return;
                    }
                    //获取阈值状态
                    Integer status = alarmRuleService.getStatusByRuleThresholdId(thresholdId);
                    if (StatusEnum.DISABLE.getCode().equals(status)) {
                        log.error("[{}], 场景ID：{} , 目标规则阈值ID：{} , 规则状态已被停用！", TAG, sceneId, thresholdId);
                        return;
                    }
                    //判断是否配置快照ID
                    if (NumberUtil.isNullOrZero(o.getCubeSnapshotId())) {
                        log.error("[{}], 场景ID：{} , 目标规则ID：{} , 未配置快照ID！", TAG, sceneId, ruleId);
                        return;
                    }
                    //获取okr子目标信息
                    ResponseDTO<ObjectiveDIO> objectiveDIOResponseDTO = objectiveRemoteService.getObjective(vo.getSubgoalId());
                    //查询责任人目标
                    ObjectiveDIO objectiveDIO = Optional.ofNullable(objectiveDIOResponseDTO.getData()).orElse(new ObjectiveDIO());
                    log.info("[{}], 查询责任人目标，目标ID：{}, okr获取目标详情接口响应：{}", TAG, vo.getSubgoalId(), JSONObject.toJSONString(objectiveDIO));
                    //判断OKR是否被禁用
                    if(StatusEnum.DISABLE.getCode().equals(objectiveDIO.getStatus())){
                        log.error("[{}], 目标ID：{} , OKR 已被禁用！！！", TAG, vo.getSubgoalId());
                        return;
                    }
                    //判断生效时间是否在当年1月1日至当前时间范围内
                    if(objectiveDIO.getValidTime() != null && (now.before(objectiveDIO.getValidTime())
                            || yearFirstDate.after(objectiveDIO.getValidTime()))){
                        log.error("[{}], 目标ID：{} , 生效时间：{}， 生效时间不在有效范围内！！！", TAG, vo.getSubgoalId(),
                                DateUtil.toString(objectiveDIO.getValidTime()));
                        return;
                    }
                    //获取okr责任人上级目标信息
                    ResponseDTO<ObjectiveDIO> deptObjectiveDIOResponseDTO = objectiveRemoteService.getObjective(Optional.ofNullable(objectiveDIO.getParentObjId()).orElse(-1));
                    //查询上级部门目标
                    ObjectiveDIO deptObjectiveDIO = Optional.ofNullable(deptObjectiveDIOResponseDTO.getData()).orElse(new ObjectiveDIO());

                    log.info("[{}], 查询责任人目标，目标ID：{}, okr获取目标详情接口响应：{}", TAG, vo.getSubgoalId(), JSONObject.toJSONString(objectiveDIO));
                    //获取每月目标值
                    List<BigDecimal> valueList = Optional.ofNullable(objectiveDIO.getValueList()).orElse(new ArrayList<>());
                    //判断是否12月目标数据
                    if (valueList.isEmpty() || valueList.size() != 12) {
                        log.error("[{}], 目标规则ID：{}, 目标ID：{}, okr目标数据错误：{}", TAG, o.getRuleId(), vo.getSubgoalId(), valueList);
                        return;
                    }
                    //获取当前时间
                    DateTime dt = new DateTime(DateUtil.getNow());
                    BigDecimal okrObjectiveValue = valueList.get(dt.getMonthOfYear() - 1);
                    if (okrObjectiveValue == null || BigDecimal.ZERO.equals(okrObjectiveValue)) {
                        log.error("[{}], 目标规则ID：{}, 当月暂无目标数据：{}", TAG, o.getRuleId(), valueList);
                        return;
                    }
                    //初始化cube快照报表入参
                    SnapshotReportDIO snapshotReportDIO = this.initParam(o, objectiveDIO);
                    //获取cube #1是目标值，#2是实际完成率，不带#的是实际统计值
                    ReportDTO<Map<String, Object>> reportDTO = boardRemoteService.getSnapshotReport(snapshotReportDIO);
                    if (!reportDTO.isSuccess()) {
                        log.error("[{}], 目标规则ID：{}, cube快照接口响应失败，响应信息：{}", TAG, o.getRuleId(), JSONObject.toJSON(reportDTO));
                        return;
                    }
                    //获取cube指标数据
                    List<Map<String, Object>> itemRows = Optional.ofNullable(reportDTO.getItemRows()).orElse(new ArrayList<>());
                    if (itemRows.isEmpty()) {
                        log.error("[{}], 目标规则ID：{}, cube快照接口响应无数据", TAG, o.getRuleId());
                        return;
                    }
                    log.info("[{}], 目标规则ID：{}, cube响应数据内容：{}，执行时间：{}", TAG, o.getRuleId(), JSONArray.toJSON(reportDTO), DateUtil.getNowFormatted());
                    Map<String, Object> data = Optional.ofNullable(itemRows.get(0)).orElse(new HashMap<>());
                    if (data.get(BrsUtil.buildKey(String.valueOf(objectiveDIO.getObjCubeId()))) == null) {
                        log.error("[{}], 目标规则ID：{}, cube未获取到当前指标数据，指标ID：{}", TAG, o.getRuleId(), objectiveDIO.getObjCubeId());
                        return;
                    }
                    //目标值
                    String objectiveValueStr = Optional.ofNullable(data.get(BrsUtil.buildCompareKey(String.valueOf(objectiveDIO.getObjCubeId())))).orElse("").toString();
                    String objectiveValueStrTemp = objectiveValueStr.replace(",","");
                    if(StringUtil.isBlank(objectiveValueStrTemp)){
                        log.error("[{}], 目标规则ID：{}, cube响应未获取到当前指标目标数据，指标ID：{}", TAG, o.getRuleId(), objectiveDIO.getObjCubeId());
                        return;
                    }
                    //如果实际值存在百分数，则转为小数
                    if (objectiveValueStrTemp.contains("%")) {
                        BigDecimal objectiveValueData = new BigDecimal(objectiveValueStrTemp.replace("%", ""));
                        objectiveValueStrTemp = objectiveValueData.divide(BigDecimal.valueOf(100)).toString();
                    }
                    BigDecimal objectiveValue = BigDecimal.valueOf(Double.parseDouble(objectiveValueStrTemp));
                    //cube指标实际值
                    String realValueStr = Optional.ofNullable(data.get(BrsUtil.buildKey(String.valueOf(objectiveDIO.getObjCubeId())))).orElse("").toString();
                    String realValueStrTemp = realValueStr.replace(",","");
                    if(StringUtil.isBlank(realValueStrTemp)){
                        log.error("[{}], 目标规则ID：{}, cube响应未获取到当前指标实际值数据，指标ID：{}", TAG, o.getRuleId(), objectiveDIO.getObjCubeId());
                        return;
                    }
                    //如果实际值存在百分数，则转为小数
                    if (realValueStrTemp.contains("%")) {
                        BigDecimal realData = new BigDecimal(realValueStrTemp.replace("%", ""));
                        realValueStrTemp = realData.divide(BigDecimal.valueOf(100)).toString();
                    }
                    BigDecimal realValue = BigDecimal.valueOf(Double.parseDouble(realValueStrTemp));
                    //目标完成率
                    String objectiveRatioValueStr = Optional.ofNullable(data.get(BrsUtil.buildCompareRatioKey(String.valueOf(objectiveDIO.getObjCubeId())))).orElse("0.0").toString();
                    if (StringUtil.isBlank(objectiveRatioValueStr)) {
                        objectiveRatioValueStr = "0.0";
                    }
                    String objectiveRatioValueStrTemp = objectiveRatioValueStr.replace(",","");
                    if(StringUtil.isBlank(objectiveRatioValueStrTemp)){
                        log.error("[{}], 目标规则ID：{}, cube响应未获取到当前指标完成率数据，指标ID：{}", TAG, o.getRuleId(), objectiveDIO.getObjCubeId());
                        return;
                    }
                    //如果实际值存在百分数，则转为小数
                    if (objectiveRatioValueStrTemp.contains("%")) {
                        objectiveRatioValueStrTemp = objectiveRatioValueStrTemp.replace("%", "");
                    }
                    BigDecimal objectiveRatioValue = BigDecimal.valueOf(Double.parseDouble(objectiveRatioValueStrTemp));
                    ObjectiveMonitor record = ObjectiveMonitor.builder()
                            .objectiveRatioValue(objectiveRatioValue.doubleValue())
                            .objectiveValue(objectiveValue)
                            .realValue(realValue)
                            .thresholdValue(o.getThresholdValue())
                            .eventCode(o.getEventCode())
                            .ruleId(o.getRuleId())
                            .subgoalId(vo.getSubgoalId())
                            .objMaster(vo.getObjMaster())
                            .objMasterType(vo.getObjMasterType())
                            .objMasterName(vo.getObjMasterName())
                            .cubeObjectiveValue(objectiveValueStr)
                            .cubeObjectiveRatioValue(objectiveRatioValueStr)
                            .cubeRealValue(realValueStr)
                            .deptId(vo.getDeptId())
                            .deptName(vo.getDeptName())
                            .subgoalDeptId(deptObjectiveDIO.getDeptId())
                            .objName(objectiveDIO.getObjName())
                            .objCubeId(objectiveDIO.getObjCubeId())
                            .thresholdId(o.getThresholdId())
                            .droolsName(o.getDroolsName())
                            .value1(ObjectiveMonitor.getRule(o.getThresholdValue(), WronLevelEnum.ONE.getLevelId()))
                            .value2(ObjectiveMonitor.getRule(o.getThresholdValue(), WronLevelEnum.TWO.getLevelId()))
                            .value3(ObjectiveMonitor.getRule(o.getThresholdValue(), WronLevelEnum.THREE.getLevelId()))
                            .sceneId(sceneId)
                            .taskId(taskId)
                            .jobType(jobType)
                            .taskVersionId(taskVersionId)
                            .build();
                    //触发规则
                    OperateRecordResult result = this.triggeringRule(record, taskVersionId);
                    //判断是否已触发监控
                    if (result.getResult()) {
                        log.info("[{}], 目标规则ID：{}, 已触发监控预警！完成率：{}，一级预警值：{}，二级预警值：{}，三级预警值：{}", TAG, o.getRuleId() ,
                                objectiveRatioValue.doubleValue(), record.getValue1() , record.getValue2() , record.getValue3());
                    } else {
                        log.info("[{}], 目标规则ID：{}, 未触发监控预警！完成率：{}，一级预警值：{}，二级预警值：{}，三级预警值：{}", TAG, o.getRuleId() ,
                                objectiveRatioValue.doubleValue(), record.getValue1() , record.getValue2() , record.getValue3());
                    }
                }catch (Exception e){
                    log.error("[{}], 场景ID：{}, 目标规则ID：{}, 触发监控异常！，异常信息：", TAG, sceneId , o.getRuleId() , e);
                }
            });
            return true;
        }catch (Exception e){
            log.error("[{}], 场景ID：{}, 触发监控异常！异常信息：{} , {}", TAG, sceneId , e.getMessage() , e);
            return false;
        }finally {
            try {
                Date endTime = DateUtil.getNow();
                Integer flag = taskVersionService.insert(TaskVersion.builder()
                        .taskId(taskId)
                        .monitorVersion(taskVersionId)
                        .monitorStartTime(now)
                        .monitorEndTime(endTime)
                        .updateTime(endTime)
                        .createTime(endTime)
                        .build());
                if(flag > 0){
                    log.info("[{}], 计算版本号：{}, 写入任务计算版本成功！", TAG, taskVersionId);
                }else {
                    log.error("[{}], 计算版本号：{}, 写入任务计算版本失败！", TAG, taskVersionId);
                }
            }catch (Exception e){
                log.error("[{}], 计算版本号：{}, 写入任务计算版本异常，异常信息：{}", TAG, taskVersionId , e);
            }
        }
    }

    /**
     * 描述：目标指标推送定时任务
     * @param job 任务
     * @param smsRuleId
     * @param pushTopic
     * @author chongw
     * @since 2021-06-07 17:50
     * @return
     */
    @Override
    public Boolean pushObjectiveTask(Job job,Integer smsRuleId, String pushTopic){
        //获取场景ID
        Integer sceneId = Integer.parseInt(job.getParam(TaskConst.SCENE_ID));
        //任务类型
        Integer jobType = Integer.parseInt(job.getParam(TaskConst.JOB_TYPE));
        try {
            //获取任务版本ID
            String taskVersionId = redisTemplate.opsForValue().get(TaskConst.getBrsSceneJobType(sceneId , jobType));
            if(StringUtil.isBlank(taskVersionId)){
                log.error("[{}], 场景ID：{} ,计算任务版本为空，执行时间：{}", TAG, sceneId, DateUtil.getNowFormatted());
                return false;
            }
            log.info("[{}], 场景ID：{} ,目标推送定时任务开始执行，执行时间：{}", TAG, sceneId, DateUtil.getNowFormatted());
            List<ObjectiveRecord> objectiveRecordList = Optional.ofNullable(objectiveRecordService.listByQuery(ObjectiveRecordQuery.builder()
                    .monitorVersion(taskVersionId)
                    .build())).orElse(new ArrayList<>());
            //推送责任人/部门负责人/上级部门负责人
            objectiveRecordList.stream().map(o -> {
                //查询监控记录日志
                String expand = o.getResult();
                //类型转换
                ObjectiveMonitorData data = JSONObject.parseObject(expand, ObjectiveMonitorData.class);
                if(WronLevelEnum.TWO.getLevelId().equals(data.getLevel())){
                    o.setParentDeptManagerId(null);
                }
                if(WronLevelEnum.ONE.getLevelId().equals(data.getLevel())){
                    o.setDeptManagerId(null);
                    o.setParentDeptManagerId(null);
                }
                return o;
            }).map(o -> {
                return new Integer[]{
                        Optional.ofNullable(o.getObjMasterId()).orElse(0L).intValue(),
                        Optional.ofNullable(o.getDeptManagerId()).orElse(0),
                        Optional.ofNullable(o.getParentDeptManagerId()).orElse(0)
                };
            }).flatMap(o -> Arrays.stream(o.clone())).filter(o -> {
                return !NumberUtil.isNullOrZero(o);
            }).distinct().forEach(o -> {
                //获取数据层级
                Integer objMasterType =  Optional.ofNullable(objectiveWarnBService.getDataLevel(Integer.parseInt(String.valueOf(o)), taskVersionId))
                        .orElse(ObjectiveMasterTypeConst.MASTERTYPE_PERSON);
                JSONObject msg = new JSONObject();
                msg.put("sceneId", sceneId);
                msg.put("jobType", jobType);
                msg.put("objMasterType", objMasterType);
                msg.put("objMasterId", o);
                msg.put("taskVersionId", taskVersionId);
                msg.put("timeStamp", System.currentTimeMillis());
                dingTalkBService.sendDingTalk(o.intValue(), msg, smsRuleId, pushTopic);
            });
            log.info("[{}], 场景ID：{} ,目标推送定时任务执行完毕，时间：{}", TAG, sceneId, DateUtil.getNowFormatted());
            return true;
        }catch (Exception e){
            log.error("[{}], 场景ID：{} ,目标推送定时任务执行异常，异常信息：{}", TAG, sceneId , e);
            return false;
        }
    }

    /**
     * 描述：目标监控触发规则
     * @param record
     * @param taskVersionId
     * @return
     */
    @Override
    @Transactional
    public OperateRecordResult triggeringRule(ObjectiveMonitor record, String taskVersionId) {
        OperateRecordResult result = OperateRecordResult.builder().result(false).build();
        long start = System.currentTimeMillis();
        KieSession kieSession = kieBaseTemplate.getKieBase().newKieSession();
        FactHandle factHandle = kieSession.insert(record);
        kieSession.setGlobal("objectiveTargetBService", this);
        RuleExecuteResultBO ruleExecuteResultBO = RuleExecuteResultBO.builder().build();
        kieSession.setGlobal("ruleExecuteResultBO", ruleExecuteResultBO);
        kieSession.fireAllRules(new AgendaFilter() {
            @Override
            public boolean accept(Match match) {
                return match.getRule().getPackageName().contains(record.getDroolsName());
            }
        });
        kieSession.delete(factHandle);
        kieSession.dispose();
        log.info("[{}]，执行规则，[耗时：{}]", TAG, System.currentTimeMillis() - start);
        long sendDDStart = System.currentTimeMillis();
        List<EventRecord> eventRecords = Optional.ofNullable(ruleExecuteResultBO.getEventRecords()).orElse(new ArrayList<>());
        if(!eventRecords.isEmpty()){
            long sendDDEnd = System.currentTimeMillis();
            log.info("[{}]，事件触发，[耗时：{}]", TAG, (sendDDEnd - sendDDStart));
            AtomicReference<Integer> flag = new AtomicReference<>(0);
            eventRecords.stream().forEach(o ->{
                flag.updateAndGet(v -> v + this.insertObjectiveRecord(o));
            });
            log.info("[{}]，保存事件记录，[耗时：{}]", TAG, (System.currentTimeMillis() - sendDDEnd));
            try{
                if(flag.get() > 0){
                    //设置redis缓存
                    redisTemplate.opsForValue().set(TaskConst.getBrsSceneJobType(record.getSceneId(),record.getJobType()), taskVersionId);
                    log.info("[{}]，保存事件记录，redis缓存task版本号：{}成功！，[耗时：{}]", TAG, taskVersionId, (System.currentTimeMillis() - sendDDEnd));
                }
            }catch (Exception e){
                log.error("[{}]，保存事件记录，redis缓存task版本号：{}，异常：", TAG, taskVersionId , e);
            }
        }
        result.setRuleExecuteResultBOs(Arrays.asList(ruleExecuteResultBO));
        result.setResult(!eventRecords.isEmpty());
        log.info("[{}]，目标监控，[总耗时：{}]", TAG, (System.currentTimeMillis() - start));
        return result;
    }


    /**
     * 保存事件结果记录及推送记录
     * @param record
     * @return
     */
    @Transactional
    protected Integer insertObjectiveRecord(EventRecord record){
        try {
            AtomicReference<Integer> flag = new AtomicReference<>(0);
            //格式化数据
            ObjectiveMonitorData data = JSONObject.parseObject(record.getExpand(), ObjectiveMonitorData.class);
            //绩效结果封装
            ObjectiveRecord objectiveRecord = ObjectiveRecord.builder()
                    .objMasterId(record.getObjectId())
                    .eventCode(record.getEventCode())
                    .monitorVersion(record.getMonitorVersion())
                    .result(record.getExpand())
                    .objMasterName(record.getRealName())
                    .level(data.getLevel())
                    .createTime(DateUtil.getNow())
                    .updateTime(DateUtil.getNow())
                    .build();
            Integer deptId = Optional.ofNullable(data.getSubgoalDeptId()).orElse(-1);
            //获取责任人所在部门
            DeptDRO dept = Optional.ofNullable(this.getDept(deptId)).orElse(new DeptDRO());
            log.info("[{}]，保存事件记录，调用mcc获取目标所在部门负责人信息接口，入参：{}，部门信息：{}", TAG, deptId, JSON.toJSONString(dept));
            if (dept != null) {
                objectiveRecord.setDeptId(dept.getDeptId());
                objectiveRecord.setDeptName(dept.getDeptName());
                objectiveRecord.setDeptManagerId(dept.getManagerId());
            }
            if (dept != null && dept.getParentId() != null) {
                //获取责任人所在部门的上级部门
                DeptDRO parentDept = Optional.ofNullable(this.getDept(dept.getParentId())).orElse(new DeptDRO());
                log.info("[{}]，保存事件记录，调用mcc获取目标所在部门上级负责人，入参：{}，部门信息：{}", TAG, dept.getParentId(), JSON.toJSONString(parentDept));
                objectiveRecord.setParentDeptId(parentDept.getDeptId());
                objectiveRecord.setParentDeptName(parentDept.getDeptName());
                objectiveRecord.setParentDeptManagerId(parentDept.getManagerId());
            }
            flag.updateAndGet(v -> v + eventRecordService.insert(record));
            //设置事件结果ID
            objectiveRecord.setEventRecordId(record.getRecordId());
            flag.updateAndGet(v -> v + objectiveRecordService.insert(objectiveRecord));
            return flag.get();
        }catch (Exception e){
            log.error("[{}]，保存事件记录，保存异常，record参数：{}，异常信息：{}", TAG, JSON.toJSONString(record), e);
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 获取部门信息
     * @param deptId
     * @return
     */
    protected DeptDRO getDept(Integer deptId){
        try {
            //获取部门信息
            ResponseDTO<DeptDRO> deptDROResponseDTO = deptListRemoteService.getDept(deptId);
            return Optional.ofNullable(deptDROResponseDTO.getData()).orElse(new DeptDRO());
        }catch (Exception e){
            log.error("[{}]，调用mcc获取部门信息接口异常，参数：{}，异常信息：{}", TAG, deptId, e);
        }
        return null;
    }

    /**
     * 描述：初始化cube入参
     * @param objectiveRuleCustom
     * @param objectiveDIO
     * @return
     * @author chongw
     * @since 2021-06-07 17:50
     */
    private SnapshotReportDIO initParam(ObjectiveRuleCustom objectiveRuleCustom,ObjectiveDIO objectiveDIO){
        log.info("[{}], 目标规则ID：{}, 初始化cube快照参数，初始化开始时间：{}", TAG, objectiveRuleCustom.getRuleId() , DateUtil.getNowFormatted());
        ObjectiveRuleVO vo = objectiveRuleCustom.getData();
        //定义快照入参
        SnapshotReportDIO snapshot = new SnapshotReportDIO();
        snapshot.setSnapshotId(objectiveRuleCustom.getCubeSnapshotId()); //快照ID
        snapshot.setDebug(true);
        snapshot.setStaffId(vo.getObjMaster()); //员工ID
        snapshot.setDayLimit(BrsConst.CUBE_SNAPSHOT_DAY_LIMIT);
        //目标配置入参
        List<CustomObjectiveDIO> objectiveConfies = new ArrayList<>();
        //定义cube业务范围
        CustomObjectiveScopeDIO objectiveScopeDIO = new CustomObjectiveScopeDIO();
        //获取okr配置的业务范围
        ResponseDTO<ObjectiveScopeDIO>  objectiveScopeResponseDTO =  objectiveRemoteService.getScopeBySubgoalId(vo.getSubgoalId());
        ObjectiveScopeDIO scopeDIO = Optional.ofNullable(objectiveScopeResponseDTO.getData()).orElse(new ObjectiveScopeDIO());
        log.info("[{}], 目标ID：{}, okr获取业务范围接口响应：{}", TAG, vo.getSubgoalId(), JSONObject.toJSONString(scopeDIO));
        //设置cube 业务范围
        BeanUtils.copyProperties(scopeDIO, objectiveScopeDIO);
        //获取每月目标值
        List<BigDecimal> valueList = objectiveDIO.getValueList();
        objectiveConfies.add(new CustomObjectiveDIO(objectiveDIO.getObjCubeId(), Arrays.asList(valueList.toArray()), objectiveScopeDIO));
        snapshot.setObjectiveConfies(objectiveConfies);
        log.info("[{}], 目标规则ID：{}, cube入参：{}，初始化完成时间：{}", TAG, objectiveRuleCustom.getRuleId() ,
                JSONObject.toJSON(snapshot), DateUtil.getNowFormatted());
        return snapshot;
    }

}
